Skip to content

feature: add AccountServiceTest unit tests with Mockito#245

Open
devin-ai-integration[bot] wants to merge 1 commit into
DevOpsfrom
devin/1781619094-account-service-tests
Open

feature: add AccountServiceTest unit tests with Mockito#245
devin-ai-integration[bot] wants to merge 1 commit into
DevOpsfrom
devin/1781619094-account-service-tests

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 16, 2026

Copy link
Copy Markdown

Summary

Adds src/test/java/com/example/bankapp/service/AccountServiceTest.java — 16 pure unit tests covering every method in AccountService, using @ExtendWith(MockitoExtension.class) with @Mock AccountRepository/TransactionRepository/PasswordEncoder and @InjectMocks AccountService.

These are mock-only tests (no Spring context / no MySQL), so they run independently of the DB-backed BankappApplicationTests.contextLoads.

Coverage:

  • deposit: balance increase + repo saves; ArgumentCaptor asserts Transaction type "Deposit" and amount.
  • withdraw: balance decrease; RuntimeException("Insufficient funds") on overdraw (asserts no saves); Transaction type "Withdrawal".
  • transferAmount: debit sender / credit recipient (mocks findByUsername(toUsername)); throws on insufficient funds; throws "Recipient account not found" on empty Optional; exactly two transactionRepository.save() calls.
  • registerAccount: creates account with BigDecimal.ZERO balance and encoded password (captor); throws "Username already exists" when present.
  • findAccountByUsername: returns account / throws "Account not found".
  • loadUserByUsername: returns UserDetails with correct username/password / throws when not found.
  • getTransactionHistory: returns transactions from findByAccountId.

Run locally with ./mvnw -Dtest=AccountServiceTest testTests run: 16, Failures: 0, Errors: 0.

Link to Devin session: https://app.devin.ai/sessions/c0c80e1f3cb9488a9bd6694801249426
Requested by: @matthewguerra-cog


Devin Review

Status Commit
🟢 Reviewed aa5bcb6
Open in Devin Review (Staging)

Co-Authored-By: Matthew Guerra <matthew.guerra@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@staging-devin-ai-integration staging-devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review (Staging)
Debug

Playground

Comment on lines +237 to +242
void loadUserByUsername_shouldThrowWhenUsernameNotFound() {
when(accountRepository.findByUsername("ghost")).thenReturn(Optional.empty());

assertThrows(RuntimeException.class,
() -> accountService.loadUserByUsername("ghost"));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 loadUserByUsername test checks RuntimeException but method contract declares UsernameNotFoundException

The loadUserByUsername_shouldThrowWhenUsernameNotFound test asserts RuntimeException.class, which is technically correct for what the implementation does — findAccountByUsername at AccountService.java:87 calls orElseThrow(() -> new RuntimeException("Account not found")) at AccountService.java:35, throwing before the UsernameNotFoundException check on line 88-89 (which is dead code). However, the UserDetailsService contract specifies that UsernameNotFoundException should be thrown. This means the test is encoding a pre-existing bug in the service rather than testing the expected Spring Security contract. If the service is later fixed to throw UsernameNotFoundException, this test will break.

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines +237 to +242
void loadUserByUsername_shouldThrowWhenUsernameNotFound() {
when(accountRepository.findByUsername("ghost")).thenReturn(Optional.empty());

assertThrows(RuntimeException.class,
() -> accountService.loadUserByUsername("ghost"));
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Test asserts RuntimeException instead of UsernameNotFoundException for loadUserByUsername

The loadUserByUsername_shouldThrowWhenUsernameNotFound test asserts RuntimeException.class is thrown. The Spring Security UserDetailsService contract expects a UsernameNotFoundException to be thrown when a user is not found. However, the actual service code at AccountService.java:87 delegates to findAccountByUsername() which throws a plain RuntimeException("Account not found") — so the test is accurately reflecting the current (arguably incorrect) service behavior. Since UsernameNotFoundException extends AuthenticationException extends RuntimeException, fixing the service to throw UsernameNotFoundException would not break this test either, making the test weaker than it could be. This is a pre-existing service issue, not a test bug.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — this is intentional. The test asserts RuntimeException because that's what the current service throws (findAccountByUsername -> RuntimeException("Account not found")), and the task spec for this test (#15) explicitly asks to "assert RuntimeException is thrown." Since UsernameNotFoundException extends RuntimeException, this assertion remains valid if the service is later hardened to throw the more specific Spring Security exception. Leaving the service behavior unchanged as it's out of scope for this test-only PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant